package cn.duckerkj.cacheclean;


import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.zip.GZIPOutputStream;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
 * js clean cache
 * @author Shensg
 * 2018年7月9日 
 */
@WebServlet(urlPatterns = {
		"*.js","*.html","*.css"
})
public class StaticCacheServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	private static final int CACHETIME=1;//秒
	private static final int MAXAGE=1;//秒
	/**
	 * 缓存
	 */
	public static Cache<String, byte[]> cache = CacheBuilder.newBuilder()  
            .expireAfterAccess(CACHETIME, TimeUnit.SECONDS).maximumSize(1000)  
            .build();  
	
	protected void service(final HttpServletRequest request,HttpServletResponse response) {
		byte[] cacheByte = null;
		/*
		 * 避免/的时候匹配错误导致
		 */
		String requestURI = request.getRequestURI().toString();
		if(requestURI.endsWith("/")) {
			requestURI+="index.html";
		}
		final String realURI = requestURI;
		try {
			System.out.println(realURI);
			/**
			 * 获取缓存的数据
			 */
			cacheByte = cache.get(realURI, new Callable<byte[]>() {

				public byte[] call() throws Exception {
					// TODO Auto-generated method stub
					//得到当前路径
					File file=new File(request.getServletContext().getRealPath("."));
					//组合成访问文件所在路径
					byte[] fileByte=null;
					file=new File(file.getParentFile(),realURI);
					//System.out.println(file.getAbsolutePath());
					//读取文件数据,将文件数据存放到内存中
					FileInputStream fin=null;
					try {
						fin = new FileInputStream(file);
						fileByte = new byte[(int) file.length()];
						fin.read(fileByte);
						return fileByte;
					} catch (FileNotFoundException e) {
						//存入 避免再次 类似redis穿透理念
						return  (realURI+"\r\n  404 No Source File").getBytes();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}finally {
						if(fin != null) {
							fin.close();
						}
					}
					return  (realURI+"\r\n  404 No Source File").getBytes();
				}
			});
		} catch (ExecutionException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//后缀判断类型
		if(request.getRequestURI().toString().endsWith(".css")) {
			response.setContentType("text/css; charset=UTF-8");
		}
		if(request.getRequestURI().toString().endsWith(".js")) {
			response.setContentType("text/javascript; charset=UTF-8");
		}
		if(request.getRequestURI().toString().endsWith(".html")
				||request.getRequestURI().toString().endsWith("/")) {
			response.setContentType("text/html; charset=UTF-8");
		}
		
		//设置静态资源过期时间
		response.addHeader("Cache-Control", "max-age="+MAXAGE);
		
		OutputStream outputStream = null;
		try {
			//输出到浏览器中
			//增加压缩
			byte[] bts = cacheByte;
			if(isGZipEncoding(request)) {
				System.out.println("压缩前大小：" + cacheByte.length);
				ByteArrayOutputStream bout = new ByteArrayOutputStream();
			    GZIPOutputStream gzipOut = new GZIPOutputStream(bout); // 创建 GZIPOutputStream 对象 
			    gzipOut.write(cacheByte); // 将响应的数据写到 Gzip 压缩流中
		        gzipOut.close(); // 将数据刷新到  bout 字节流数组
		        bts = bout.toByteArray();
		        System.out.println("压缩后大小：" + bts.length);
		        response.setHeader("Content-Encoding", "gzip"); // 设置响应头信息
			}
	        //将压缩数据相应客户端
			outputStream = response.getOutputStream();
			outputStream.write(bts);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
	}
	private static boolean isGZipEncoding(HttpServletRequest request){
		boolean flag = false;
		String encoding = request.getHeader("Accept-Encoding");
		// update-begin--Author:JueYue Date:20140518
		// for：IE下Excel上传encode为空的bug--------------------
		if (encoding != null && encoding.indexOf("gzip") != -1) {
			flag = true;
		}
		// update-end--Author:JueYue Date:20140518
		// for：IE下Excel上传encode为空的bug--------------------
		return flag;
	}
}
